package com.xnew.aes;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import com.xnew.operator.bean.AcctOperatorLog;
import com.xnew.operator.service.AcctOperatorLogService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * @author monkey
 * @desc 请求数据解密
 * @date 2018/10/25 20:17
 */
@ControllerAdvice
public class DecodeRequestBodyAdvice implements RequestBodyAdvice {
	
	final Map<String,String> map = new HashMap<String,String>();
 
	@Autowired
    private AcctOperatorLogService acctOperatorLogService;
    private static final Logger logger = LoggerFactory.getLogger(DecodeRequestBodyAdvice.class);
    
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }
 
    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return body;
    }
 
    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
//    	try {
//    		HttpHeaders headers = inputMessage.getHeaders();
//            String times = String.valueOf(System.currentTimeMillis());
//                    //headers.get("times").get(0);
//            boolean encode = false;
//            if (methodParameter.getMethod().isAnnotationPresent(SecurityParameter.class)) {
//                //获取注解配置的包含和去除字段
//                SecurityParameter serializedField = methodParameter.getMethodAnnotation(SecurityParameter.class);
//                //入参是否需要解密
//                encode = serializedField.inDecode();
//            }
//            HttpInputMessage httpInputMessage = new MyHttpInputMessage(inputMessage, encode);
//            String desc = "";
//            String key = "";
//            if (methodParameter.getMethod().isAnnotationPresent(LogParameter.class)) {
//	        	LogParameter serializedLogField = methodParameter.getMethodAnnotation(LogParameter.class);
//	        	desc = serializedLogField.desc();
//	        	key = serializedLogField.key();
//	        	this.saveOperatorLog(times, map.get("requestBody"), desc, key);
//	        }
//            return httpInputMessage;
            return inputMessage;
//            if (encode) {
////                logger.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密");
//                HttpInputMessage httpInputMessage = new MyHttpInputMessage(inputMessage);
////                if (methodParameter.getMethod().isAnnotationPresent(LogParameter.class)) {
////                	LogParameter serializedLogField = methodParameter.getMethodAnnotation(LogParameter.class);
////                	this.saveOperatorLog(httpInputMessage, serializedLogField.desc(), serializedLogField.key());
////                }
//                return httpInputMessage;
//            }else{
//            	if (methodParameter.getMethod().isAnnotationPresent(LogParameter.class)) {
//            		LogParameter serializedLogField = methodParameter.getMethodAnnotation(LogParameter.class);
//                	this.saveOperatorLog(inputMessage, serializedLogField.desc(), serializedLogField.key());
//                }
//                return inputMessage;
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
////            logger.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常："+e.getMessage());
//            return inputMessage;
//        }
    }
    
    public void saveOperatorLog(String times, String requestBody, String desc, String key){
    	try {
            //保存操作日志
            AcctOperatorLog acctOperatorLog = new AcctOperatorLog();
            acctOperatorLog.setAolId(times);
            acctOperatorLog.setRequestParam(requestBody);
            acctOperatorLog.setAolDesc(desc);
            JSONObject json = JSON.parseObject(requestBody);
            String value = "";
            if(null != key && !"".equals(key)) {
                if(null == json.getString(key)){
                    if(null != json.getJSONObject("param") && null != json.getJSONObject("param").getString(key)){
                        value = json.getJSONObject("param").getString(key);
                    }
                }else{
                    value = json.getString(key);
                }
            }
            acctOperatorLog.setRequestKey(key+":"+value);
            acctOperatorLogService.insertOperator(acctOperatorLog);
    	}catch (Exception e) {
			e.printStackTrace();
		}
    }
 
    @Override
    public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
//        String desc = "";
//        String key = "";
//        HttpHeaders headers = httpInputMessage.getHeaders();
//        String times = headers.get("times").get(0);
//        if (methodParameter.getMethod().isAnnotationPresent(LogParameter.class)) {
//            LogParameter serializedLogField = methodParameter.getMethodAnnotation(LogParameter.class);
//            desc = serializedLogField.desc();
//            key = serializedLogField.key();
//            this.saveOperatorLog(times, JSONObject.toJSONString(body), desc, key);
//        }
        return body;
    }
 
    class MyHttpInputMessage implements HttpInputMessage {
    	
        private HttpHeaders headers;
 
        private InputStream body;
 
        public MyHttpInputMessage(HttpInputMessage inputMessage, boolean encode) throws Exception {
//            if(encode) {
//            	this.headers = inputMessage.getHeaders();
//                List<String> list = headers.get("token");
//                String key = null;
//                if(null == list || list.size() == 0 || "".equals(list.get(0)) || !RedisUtil.exists(list.get(0))) {
//                	key = AesEncryptUtils.KEY;
//                }else {
//                	key = RedisUtil.get("AES_KEY:"+list.get(0));
//                }
//                String requestBody = AesEncryptUtils.decrypt(easpString(IOUtils.toString(inputMessage.getBody(), "UTF-8")), key);
//                map.put("requestBody", requestBody);
//                this.body = IOUtils.toInputStream(requestBody, "UTF-8");
//            }else {
//                String requestBody = IOUtils.toString(inputMessage.getBody(), "UTF-8");
//                map.put("requestBody", requestBody);
////                this.body = IOUtils.toInputStream(requestBody, "UTF-8");
//            }
        }
 
        @Override
        public InputStream getBody() throws IOException {
            return body;
        }
 
        @Override
        public HttpHeaders getHeaders() {
            return headers;
        }
 
        /**
         *
         * @param requestData
         * @return
         */
        public String easpString(String requestData){
            if(requestData != null && !requestData.equals("")){
                String s = "{\"requestData\":";
                if(!requestData.startsWith(s)){
                    throw new RuntimeException("参数【requestData】缺失异常！");
                }else{
                    int closeLen = requestData.length()-1;
                    int openLen = "{\"requestData\":".length();
                    String substring = StringUtils.substring(requestData, openLen, closeLen);
                    return substring;
                }
            }
            return "";
        }
	}
}